package cn.zk.group.server;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * handler
 *
 * ChannelInboundHandlerAdapter 是 ChannelInboundHandlerAdapter的子类
 */
public class NettyGroupChatHandler extends SimpleChannelInboundHandler<String> {

    // netty提供管理channel的容器，这里用来管理所有的在线用户(channel)
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    // 时间格式化
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 读取客户端的数据 -> 群发消息
     * 自己发的消息要做区分
     * @param channelHandlerContext
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception {
        Channel channel = channelHandlerContext.channel();
        channelGroup.forEach(c -> {
            if(channel != c) {// 不是当前channel
                c.writeAndFlush("==>"+sdf.format(new Date())
                        +" ["+channel.remoteAddress()+"]"+" : "+msg);
            } else { // 是当前channel
                c.writeAndFlush("==>"+sdf.format(new Date())
                        +" [自己]"+" : "+msg);
            }
        });
    }

    /**
     * 客户端建立连接时回触发该方法 -> 客户端上线
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 加入到channelGroup中管理
        channelGroup.add(channel);
        // writeAndFlush：netty底层会遍历所有的channel执行操作
        channelGroup.writeAndFlush("==>"+sdf.format(new Date())
                +" ["+channel.remoteAddress()+"]"+" 加入聊天室！");
    }

    /**
     * 客户端断开连接时回触发该方法 -> 客户端下线
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // writeAndFlush：netty底层会遍历所有的channel执行操作,并且会自动remove掉该channel
        channelGroup.writeAndFlush("==>"+sdf.format(new Date())
                +"["+channel.remoteAddress()+"]"+" 退出聊天室！");
        System.out.println("==>当前在线用户: "+channelGroup.size());
    }

    /**
     * channel 活跃
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        System.out.println("==>"+sdf.format(new Date())
                +" ["+channel.remoteAddress()+"]"+" 已经上线！");
    }

    /**
     * channel 不活跃
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        System.out.println("==>"+sdf.format(new Date())
                +" ["+channel.remoteAddress()+"]"+" 已经下线！");
    }

    /**
     * 出现异常会触发该方法 -> 关闭channel
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 关闭
        ctx.close();
    }

}
